/*!
 * \file tbinary.c
 *
 * \brief 共通定义
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 共通使用的宏和结构体
 *
 * \version 1.0
 * \author jikw
 * \date 2017/02/09
 *
 */

#include "config.h"
#include "frsutl.h"
#include "frhash2.h"
#include "frct_comm.h"
#include "frservice_comm.h"
#include "frct_detect_hash.h"
#include "frvar_field.h"
#include "../comm/thrift_comm.h"
#include "tbinary.h"

struct timeval g_st_time_tbinary;
extern void *g_p_apm_context;
FR_STATIC int __tbinary_readobject(Frbyte_Packet *p_packet, L7session_thrift_private *p_st_private, Frreport_body_data *p_st_body_data, char *p_name);

/*!
 * 链表查找规则
 *
 * \Frlist_node *p_st_node
 * \const void *p_compare_data
 *
 * \return int
 *
 * \note
 *
 */
FR_STATIC int __fields_list_node_find(Frlist_node *p_st_node, const void *p_compare_data)
{
    if (p_st_node == NULL)
        return 1;

    if (((thrift_data *)(p_st_node->data))->i_seq_id == *((int*)p_compare_data))
        return 0;
    else
        return 1;
}

/*!
 * 检查是否超时
 *
 * \param p_node
 * \param p_data
 *
 * \return int
 *
 * \note
 *
 */
FR_STATIC int __check_timeout(Frlist_node* p_node, const void *p_data)
{
    thrift_data *p_st_info = NULL;
    Frlist_header *p_header = (Frlist_header *)p_data;

    p_st_info = (thrift_data *)p_node->data;

    if (p_st_info->st_l4_trans.st_request_time.tv_sec + TIMEOUT <= g_st_time_tbinary.tv_sec)
        frlist_node_free(p_header, p_node, FR_YES, frthritf_list_node_free);

    return 1;
}

/*!
 * 清除list中超时的node
 *
 * \param p_header
 * \param st_timestamp
 *
 * \return int
 *
 * \note
 *
 */
FR_STATIC void __clear_timeout_node(Frlist_header *p_header, struct timeval st_timestamp)
{
    g_st_time_tbinary = st_timestamp;
    frlist_run(p_header, p_header, __check_timeout);

    return;
}

/*!
 * 判断是否是tbinary协议
 *
 * \param p_st_conn       (输入数据信息)
 * \param p_st_packet     (输入数据)
 *
 * \return APM_L7_IS_YES  属于tbinary协议\n
 *         APM_L7_IS_NO   不属于tbinary协议
 *
 * \note
 *
 */
int thrift_tbinary_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    int i_ret = 0;
	int i_version = 0x80;

    if (p_st_conn==NULL || p_st_packet == NULL)
        return APM_L7_IS_NO;
    if (p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len == 0)
        return APM_L7_IS_NO;

    //表示方式一：
    //4个字节的版本信息（含调用类型）
    //4个字节的消息名称长度、消息名称
    //4个字节的流水号
    //消息负载数据的值
    //1个字节的结束标记

    //表示方式二：
    //4个字节的消息名称长度、消息名称
    //1个字节的调用类型
    //4个字节的流水号
    //消息负载数据的值
    //1个字节的结束标记

    //32位版本信息 请求报文0x80010001 响应报文0x80010002 异常报文0x80010003 无返回值请求0x80010004
    if (memcmp(p_st_packet->p_payload, "\x80\x01\x00", 3) != 0)
        goto ERROR;
    if (*(p_st_packet->p_payload+3) < '\x01' || *(p_st_packet->p_payload+3) > '\x04')
        goto ERROR;
    //以0x00结尾 分片包不会
    //if (*(p_st_packet->p_payload+p_st_packet->ui_payload_len-1) != '\x00')
    //    goto ERROR;

    i_ret = frct_get_direct_known(p_st_conn);
    if (i_ret == FR_DIRECT_UNKNOWN)
    {
        if (*(p_st_packet->p_payload+3) == '\x01' || *(p_st_packet->p_payload+3) == '\x04')//req
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
        if (*(p_st_packet->p_payload+3) == '\x02' || *(p_st_packet->p_payload+3) == '\x03')//resp
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
    }
    if (*(p_st_packet->p_payload+3) == '\x01' || *(p_st_packet->p_payload+3) == '\x04')//req
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, &i_version, sizeof(int));
    if (*(p_st_packet->p_payload+3) == '\x02' || *(p_st_packet->p_payload+3) == '\x03')//resp
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, &i_version, sizeof(int));

    return APM_L7_IS_YES;

ERROR:
    return APM_L7_IS_NO;
}

/*!
 * __tbinary_readobject
 *
 * \param p_packet
 * \param p_st_body_data
 * \param p_st_private
 * \param p_name          ("request.rpc.arg.%d"或"response.rpc.return.%d")
 * \param u8_type
 *
 * \return FR_FAIL        失败\n
 *         FR_SUCC        成功
 *
 * \note
 *
 */
FR_STATIC int __tbinary_readobject_twice(Frbyte_Packet *p_packet, L7session_thrift_private *p_st_private, Frreport_body_data *p_st_body_data, char *p_name, uint8_t u8_input)
{
    uint8_t u8_len = 0;
    uint8_t u8_key_type = 0;
    uint8_t u8_value_type = 0;
    uint32_t u32_int = 0;

    int8_t i8_len = 0;
    int16_t i16_short = 0;
    int32_t i32_int = 0;
    int64_t i64_long = 0;

    int i_count = 0;
    char *p_value = NULL;
    char arr_name[ARRAY_LEN] = {0};
    char arr_temp[ARRAY_LEN] = {0};
    union int64_double_bits u_64bits;

    if (p_packet == NULL || p_st_private == NULL || p_st_body_data == NULL ||  p_name == NULL)
        return FR_FAIL;

    memset(arr_name, 0x00, sizeof(arr_name));
    memset(arr_temp, 0x00, sizeof(arr_temp));

    switch (u8_input)
    {
        case 0x02://BOOL
            if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
                return FR_FAIL;
            if (u8_len == 0x00)
            {
                if (frreport_body_l7_add_str(p_st_body_data, p_name, "false") == FR_FAIL)
                    return FR_FAIL;
            }
            else if (u8_len == 0x01)
            {
                if (frreport_body_l7_add_str(p_st_body_data, p_name, "true") == FR_FAIL)
                    return FR_FAIL;
            }
            else
                return FR_FAIL;
            break;

        case 0x03://BYTE
            if (bytebuff_get_bytes(p_packet, arr_temp, 1) == FR_FAIL)
                return FR_FAIL;
            if (frreport_body_l7_add_bin(p_st_body_data, p_name, arr_temp, 1) == FR_FAIL)
                goto ERROR;
            break;

        case 0x04://DOUBLE
            if (bytebuff_get_char(p_packet, (uint8_t *)&i8_len) == FR_FAIL)
                return FR_FAIL;
            u_64bits.int_bits = i8_len;
            if (frreport_body_l7_add_double(p_st_body_data, p_name, u_64bits.double_bits) == FR_FAIL)
                return FR_FAIL;
            if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
                return FR_FAIL;
            if (u8_len != 0x00)
                return FR_FAIL;
            break;

        case 0x06://I16
            if (bytebuff_get_short(p_packet, 2, (uint16_t *)&i16_short, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            if (frreport_body_l7_add_int(p_st_body_data, p_name, i16_short) == FR_FAIL)
                return FR_FAIL;
            break;

        case 0x08://I32
            if (bytebuff_get_int(p_packet, 4, (uint32_t *)&i32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            if (frreport_body_l7_add_int(p_st_body_data, p_name, i32_int) == FR_FAIL)
                return FR_FAIL;
            break;

        case 0x0a://I64
            if (bytebuff_get_long(p_packet, 8, (uint64_t *)&i64_long, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            if (frreport_body_l7_add_long(p_st_body_data, p_name, i64_long) == FR_FAIL)
                return FR_FAIL;
            break;

        case 0x0b://STRING
            if (bytebuff_get_int(p_packet, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            p_value = (char *)frmalloc(u32_int+1);
            if (p_value == NULL)
                goto ERROR;
            memset(p_value, 0x00, u32_int+1);
            if (bytebuff_get_bytes(p_packet, p_value, u32_int) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, p_name, p_value) == FR_FAIL)
                goto ERROR;
            frfree(p_value);
            p_value = NULL;
            break;

        case 0x0c://STRUCT
            while (1)
            {
                //TType.STOP = 0;遇到结束标记结束循环
                if (bytebuff_peek_char(p_packet, &u8_len) == FR_FAIL)
                    return FR_FAIL;
                if (u8_len == '\x00')
                {
                    if (bytebuff_skip(p_packet, 1) != FR_SUCC)
                        return FR_FAIL;
                    break;
                }

                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.struct.%d", p_name, i_count+1);
                if (__tbinary_readobject(p_packet, p_st_private, p_st_body_data, arr_name) == FR_FAIL)
                    return FR_FAIL;
                i_count += 1;
            }
            break;

        case 0x0d://MAP
            //取key、value的类型 各一位
            if (bytebuff_get_char(p_packet, &u8_key_type) == FR_FAIL)
                return FR_FAIL;
            if (bytebuff_get_char(p_packet, &u8_value_type) == FR_FAIL)
                return FR_FAIL;
            //取map中的元素个数
            if (bytebuff_get_int(p_packet, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            for (i_count = 0; i_count<(int)u32_int; i_count++)
            {
                //根据key类型取key值上报
                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.%d.key", p_name, i_count+1);
                if (__tbinary_readobject_twice(p_packet, p_st_private, p_st_body_data, arr_name,u8_key_type) == FR_FAIL)
                    return FR_FAIL;
                //根据value类型取value值上报
                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.%d.value", p_name, i_count+1);
                if (__tbinary_readobject_twice(p_packet, p_st_private, p_st_body_data, arr_name,u8_value_type) == FR_FAIL)
                    return FR_FAIL;
            }
            break;

        case 0x0e://SET
            //取set的值的类型 1位
            if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
                return FR_FAIL;
            //取set里面的元素个数 4位
            if (bytebuff_get_int(p_packet, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            for (i_count = 0; i_count<(int)u32_int; i_count++)
            {
                //循环取set元素并上报
                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.set.%d", p_name, i_count+1);
                if (__tbinary_readobject_twice(p_packet, p_st_private, p_st_body_data, arr_name, u8_len) == FR_FAIL)
                    return FR_FAIL;
            }
            break;

        case 0x0f://LIST
            //取list值的类型
            if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
                return FR_FAIL;
            //取set里面的元素个数 4位
            if (bytebuff_get_int(p_packet, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            for (i_count = 0; i_count<(int)u32_int; i_count++)
            {
                //循环取list元素并上报
                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.list.%d", p_name, i_count+1);
                if (__tbinary_readobject_twice(p_packet, p_st_private, p_st_body_data, arr_name, u8_len) == FR_FAIL)
                    return FR_FAIL;
            }
            break;

        default:
            return FR_FAIL;
            break;
    }

    return FR_SUCC;

ERROR:
    if (p_value)
        frfree(p_value);
    return FR_FAIL;
}

/*!
 * __tbinary_readobject
 *
 * \param p_packet
 * \param p_st_body_data
 * \param p_st_private
 * \param p_name          ("request.rpc.arg.%d"或"response.rpc.return.%d")
 *
 * \return FR_FAIL        失败\n
 *         FR_SUCC        成功
 *
 * \note
 *
 */
FR_STATIC int __tbinary_readobject(Frbyte_Packet *p_packet, L7session_thrift_private *p_st_private, Frreport_body_data *p_st_body_data, char *p_name)
{
    uint8_t u8_len = 0;
    uint8_t u8_key_type = 0;
    uint8_t u8_value_type = 0;
    uint32_t u32_int = 0;

    int8_t i8_len = 0;
    int16_t i16_short = 0;
    int32_t i32_int = 0;
    int64_t i64_long = 0;

    int i_count = 0;
    char *p_value = NULL;
    char arr_name[ARRAY_LEN] = {0};
    char arr_temp[ARRAY_LEN] = {0};
    union int64_double_bits u_64bits;

    if (p_packet == NULL || p_st_private == NULL || p_st_body_data == NULL ||  p_name == NULL)
        return FR_FAIL;

    memset(arr_name, 0x00, sizeof(arr_name));
    memset(arr_temp, 0x00, sizeof(arr_temp));

    if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
        return FR_FAIL;

    switch (u8_len)
    {
        case 0x02://BOOL
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
                return FR_FAIL;
            if (u8_len == 0x00)
            {
                if (frreport_body_l7_add_str(p_st_body_data, p_name, "false") == FR_FAIL)
                    return FR_FAIL;
            }
            else if (u8_len == 0x01)
            {
                if (frreport_body_l7_add_str(p_st_body_data, p_name, "true") == FR_FAIL)
                    return FR_FAIL;
            }
            else
                return FR_FAIL;
            break;

        case 0x03://BYTE
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            if (bytebuff_get_bytes(p_packet, arr_temp, 1) == FR_FAIL)
                return FR_FAIL;
            if (frreport_body_l7_add_bin(p_st_body_data, p_name, arr_temp, 1) == FR_FAIL)
                goto ERROR;
            break;

        case 0x04://DOUBLE
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            if (bytebuff_get_char(p_packet, (uint8_t *)&i8_len) == FR_FAIL)
                return FR_FAIL;
            u_64bits.int_bits = i8_len;
            if (frreport_body_l7_add_double(p_st_body_data, p_name, u_64bits.double_bits) == FR_FAIL)
                return FR_FAIL;
            if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
                return FR_FAIL;
            if (u8_len != 0x00)
                return FR_FAIL;
            break;

        case 0x06://I16
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            if (bytebuff_get_short(p_packet, 2, (uint16_t *)&i16_short, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            if (frreport_body_l7_add_int(p_st_body_data, p_name, i16_short) == FR_FAIL)
                return FR_FAIL;
            break;

        case 0x08://I32
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            if (bytebuff_get_int(p_packet, 4, (uint32_t *)&i32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            if (frreport_body_l7_add_int(p_st_body_data, p_name, i32_int) == FR_FAIL)
                return FR_FAIL;
            break;

        case 0x0a://I64
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            if (bytebuff_get_long(p_packet, 8, (uint64_t *)&i64_long, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            if (frreport_body_l7_add_long(p_st_body_data, p_name, i64_long) == FR_FAIL)
                return FR_FAIL;
            break;

        case 0x0b://STRING
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            if (bytebuff_get_int(p_packet, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            p_value = (char *)frmalloc(u32_int+1);
            if (p_value == NULL)
                goto ERROR;
            memset(p_value, 0x00, u32_int+1);
            if (bytebuff_get_bytes(p_packet, p_value, u32_int) == FR_FAIL)
                goto ERROR;
            if (frreport_body_l7_add_str(p_st_body_data, p_name, p_value) == FR_FAIL)
                goto ERROR;
            frfree(p_value);
            p_value = NULL;
            break;

        case 0x0c://STRUCT
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            while (1)
            {
                //TType.STOP = 0;遇到结束标记结束循环
                if (bytebuff_peek_char(p_packet, &u8_len) == FR_FAIL)
                    return FR_FAIL;
                if (u8_len == '\x00')
                {
                    if (bytebuff_skip(p_packet, 1) != FR_SUCC)
                        return FR_FAIL;
                    break;
                }

                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.struct.%d", p_name, i_count+1);
                if (__tbinary_readobject(p_packet, p_st_private, p_st_body_data, arr_name) == FR_FAIL)
                    return FR_FAIL;
                i_count += 1;
            }
            break;

        case 0x0d://MAP
            //跳过元素编号
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            //取key、value的类型 各一位
            if (bytebuff_get_char(p_packet, &u8_key_type) == FR_FAIL)
                return FR_FAIL;
            if (bytebuff_get_char(p_packet, &u8_value_type) == FR_FAIL)
                return FR_FAIL;
            //取map中的元素个数
            if (bytebuff_get_int(p_packet, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            for (i_count = 0; i_count<(int)u32_int; i_count++)
            {
                //根据key类型取key值上报
                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.%d.key", p_name, i_count+1);
                if (__tbinary_readobject_twice(p_packet, p_st_private, p_st_body_data, arr_name,u8_key_type) == FR_FAIL)
                    return FR_FAIL;
                //根据value类型取value值上报
                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.%d.value", p_name, i_count+1);
                if (__tbinary_readobject_twice(p_packet, p_st_private, p_st_body_data, arr_name,u8_value_type) == FR_FAIL)
                    return FR_FAIL;
            }
            break;

        case 0x0e://SET
            //跳过元素编号
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            //取set的值的类型 1位
            if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
                return FR_FAIL;
            //取set里面的元素个数 4位
            if (bytebuff_get_int(p_packet, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            for (i_count = 0; i_count<(int)u32_int; i_count++)
            {
                //循环取set元素并上报
                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.set.%d", p_name, i_count+1);
                if (__tbinary_readobject_twice(p_packet, p_st_private, p_st_body_data, arr_name, u8_len) == FR_FAIL)
                    return FR_FAIL;
            }
            break;

        case 0x0f://LIST
            //跳过元素编号
            if (bytebuff_skip(p_packet, 2) != FR_SUCC)
                return FR_FAIL;
            //取list值的类型
            if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
                return FR_FAIL;
            //取set里面的元素个数 4位
            if (bytebuff_get_int(p_packet, 4, &u32_int, BYTE_BIG_ENDIAN) == FR_FAIL)
                return FR_FAIL;
            for (i_count = 0; i_count<(int)u32_int; i_count++)
            {
                //循环取list元素并上报
                memset(arr_name, 0x00, sizeof(arr_name));
                snprintf(arr_name, sizeof(arr_name), "%s.list.%d", p_name, i_count+1);
                if (__tbinary_readobject_twice(p_packet, p_st_private, p_st_body_data, arr_name, u8_len) == FR_FAIL)
                    return FR_FAIL;
            }
            break;

        default:
            return FR_FAIL;
            break;
    }

    return FR_SUCC;

ERROR:
    if (p_value)
        frfree(p_value);
    return FR_FAIL;
}

/*!
 * req数据解析
 *
 * \param p_packet        (req数据)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __req_parse(Frbyte_Packet *p_packet
                        , L7session_thrift_private *p_st_private
                        , Frreport_body_data *p_st_body_data
                        , Conntrack *p_st_conn)
{
    uint8_t u8_len = 0;
    uint32_t u32_len = 0;
    int i_count = 0;
    char *p_value = NULL;
    char arr_temp[ARRAY_LEN] = {0};
    char arr_name[ARRAY_LEN] = {0};

    if (p_packet == NULL || p_st_private == NULL || p_st_body_data == NULL || p_st_conn == NULL)
        return APM_L7_ANALYZE_FAIL;

    memset(arr_temp, 0x00, sizeof(arr_temp));
    memset(arr_name, 0x00, sizeof(arr_name));

    //版本
    if (bytebuff_get_bytes(p_packet, arr_temp, 3) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (memcmp(arr_temp, "\x80\x01\x00", 3) != 0)
        return APM_L7_ANALYZE_FAIL;

    //函数调用 1请求 2响应 3异常 4无返回值请求
    if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (u8_len == 0x04)
    {
        if (frreport_body_l7_add_int(p_st_body_data, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 0) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        p_st_private->i_flag_oneway = 1;
    }
    else if (u8_len == 0x01)
    {
        if (frreport_body_l7_add_int(p_st_body_data, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 1) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        p_st_private->i_flag_oneway = 0;
    }
    else
        return APM_L7_ANALYZE_FAIL;

    //消息名称
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    p_value = (char *)frmalloc(u32_len+1);
    if (p_value == NULL)
        goto ERROR;
    memset(p_value, 0x00, u32_len+1);
    if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
        goto ERROR;
    if (frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, p_value) == FR_FAIL)
        goto ERROR;
    frfree(p_value);
    p_value = NULL;

    //消息流水号
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    p_st_private->i_req_id = u32_len;

    //循环取消息负载数据的值
    while (1)
    {
        //TType.STOP = 0;遇到结束标记结束循环
        if (bytebuff_peek_char(p_packet, &u8_len) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        if (u8_len == '\x00')
        {
            if (bytebuff_skip(p_packet, 1) != FR_SUCC)
                return APM_L7_ANALYZE_FAIL;
            break;
        }

        memset(arr_name, 0x00, sizeof(arr_name));
        snprintf(arr_name, sizeof(arr_name), "request.rpc.arg.%d", i_count+1);
        if (__tbinary_readobject(p_packet, p_st_private, p_st_body_data, arr_name) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        i_count += 1;
    }

    //遇到结束标记结束循环 判断之后是否还有数据
    if (p_packet->ui_remaining > 0)
        return APM_L7_ANALYZE_FAIL;

    return APM_L7_ANALYZE_SUCC;

ERROR:
    if (p_value)
        frfree(p_value);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * resp数据解析
 *
 * \param p_packet   (resp数据)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __resp_parse(Frbyte_Packet *p_packet
                         , L7session_thrift_private *p_st_private
                         , Frreport_body_data *p_st_body_data
                         , Conntrack *p_st_conn)
{
    uint8_t u8_len = 0;
    uint32_t u32_len = 0;
    int i_count = 0;
    char *p_value = NULL;
    char arr_temp[ARRAY_LEN] = {0};
    char arr_name[ARRAY_LEN] = {0};

    if (p_packet == NULL || p_st_private == NULL || p_st_body_data == NULL || p_st_conn == NULL)
        return APM_L7_ANALYZE_FAIL;

    memset(arr_temp, 0x00, sizeof(arr_temp));
    memset(arr_name, 0x00, sizeof(arr_name));

    //版本
    if (bytebuff_get_bytes(p_packet, arr_temp, 3) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (memcmp(arr_temp, "\x80\x01\x00", 3) != 0)
        return APM_L7_ANALYZE_FAIL;

    //函数调用 1请求 2响应 3异常 4无返回值请求
    if (bytebuff_get_char(p_packet, &u8_len) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (u8_len != 0x02 && u8_len != 0x03)
        return APM_L7_ANALYZE_FAIL;

    //消息名称
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    p_value = (char *)frmalloc(u32_len+1);
    if (p_value == NULL)
        goto ERROR;
    memset(p_value, 0x00, u32_len+1);
    if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
        goto ERROR;
    if (frreport_body_l7_add_str(p_st_body_data, "response.rpc.return", p_value) == FR_FAIL)
        goto ERROR;
    frfree(p_value);
    p_value = NULL;

    //消息流水号
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    p_st_private->i_resp_id = u32_len;

    //循环取消息负载数据的值
    while (1)
    {
        //TType.STOP = 0;遇到结束标记结束循环
        if (bytebuff_peek_char(p_packet, &u8_len) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        if (u8_len == '\x00')
        {
            if (bytebuff_skip(p_packet, 1) != FR_SUCC)
                return APM_L7_ANALYZE_FAIL;
            break;
        }

        memset(arr_name, 0x00, sizeof(arr_name));
        snprintf(arr_name, sizeof(arr_name), "response.rpc.return.%d", i_count+1);
        if (__tbinary_readobject(p_packet, p_st_private, p_st_body_data, arr_name) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
        i_count += 1;
    }

    //遇到结束标记结束循环 判断之后是否还有数据
    if (p_packet->ui_remaining > 0)
        return APM_L7_ANALYZE_FAIL;

    return APM_L7_ANALYZE_SUCC;

ERROR:
    if (p_value)
        frfree(p_value);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * req的p_report_comm、p_report_req、starttime和编号存进链表
 *
 * \param p_st_private    (私有数据)
 *
 * \return FR_FAIL        失败\n
 *         FR_SUCC        成功
 *
 * \note
 *
 */
FR_STATIC int __tbinary_add_req_list(L7session_thrift_private *p_st_private, Frreport_body_data *p_st_body_data)
{
    thrift_data *p_st_report = NULL;
	Frlist_node *p_st_node = NULL;
	Frlist_node *p_st_gotnode = NULL;
	L4_transaction *p_st_l4_trans = NULL;

    if (p_st_private == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    //创建链表
    //if (p_st_private->st_thrift_data_list == NULL)
    //   p_st_private->st_thrift_data_list = frlist_create();

    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //把req的p_report_comm、p_report_req和ID和编号存进链表
    p_st_report = (thrift_data *)frmalloc(sizeof(thrift_data));
    memset(p_st_report, 0x00, sizeof(thrift_data));

    memcpy(&p_st_report->st_l4_trans, p_st_l4_trans, sizeof(L4_transaction));

    //拷贝相关链表
    p_st_report->p_report_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_body_data);
    if (p_st_report->p_report_comm == NULL)
        goto ERROR;
    p_st_report->p_report_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_body_data);
    if (p_st_report->p_report_req == NULL)
        goto ERROR;

    p_st_report->i_seq_id = p_st_private->i_req_id;

    p_st_node = frlist_node_create(p_st_report);
    //存list之前 判断key值是否存在 如存在删除节点 再加节点
    p_st_gotnode = frlist_find(&(p_st_private->st_thrift_data_list), &(p_st_private->i_req_id), __fields_list_node_find);
    if (p_st_gotnode != NULL)
        frlist_node_free(&p_st_private->st_thrift_data_list, p_st_gotnode, FR_YES, frthritf_list_node_free);

    frlist_add_tail(&p_st_private->st_thrift_data_list, p_st_node);

    return FR_SUCC;

ERROR:
    if (p_st_report)
        frfree(p_st_report);
    if (p_st_report->p_report_comm)
        frreport_body_l7list_free(&p_st_report->p_report_comm);
    if (p_st_report->p_report_req)
        frreport_body_l7list_free(&p_st_report->p_report_req);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * req解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
int thrift_tbinary_req_analyze(Conntrack *p_st_conn
                                , Apm_packet *p_st_packet
                                , Frhash_header *p_st_hash_report
                                , L7_session *p_st_session)
{
    int i_ret = 0;
    unsigned long ul_tmp = 0;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data* p_st_report_data = NULL;
    L7session_thrift_private *p_st_private = NULL;
    Frreport_body_data *p_st_body_data = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_thrift_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //创建数据链表
    if (p_st_body_data == NULL)
    {
        p_st_body_data = frreport_body_new_l7(p_st_conn);
        if (p_st_body_data == NULL)
            goto ERROR;

        if (frreport_body_l7_add_connInfo(p_st_body_data, p_st_conn) == FR_FAIL)
            goto ERROR;

        if (p_st_l4_trans->st_request_time_first_byte.tv_sec==0 && p_st_l4_trans->st_request_time_first_byte.tv_usec==0)
        {
            //st_request_time_first_byte
            p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_st_data == NULL)
        {
            p_st_private->p_st_data = bytebuff_creat();
            if (p_st_private->p_st_data == NULL)
                goto ERROR;
        }
    }
    //请求的字节数
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_st_data == NULL)
        goto ERROR;
    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    //分片包判断
    if (*(p_st_packet->p_payload+p_st_packet->ui_payload_len-1) != '\x00')
    {
        frreport_body_free(&p_st_body_data);
        return APM_L7_ANALYZE_TODO;
    }

    //req解析
    i_ret = __req_parse(p_st_private->p_st_data, p_st_private, p_st_body_data, p_st_conn);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    //数据上报
    if (frreport_body_l7_add_ulong(p_st_body_data, APM_REPORT_KEY_REQ_ID, frct_seq_increase(p_st_conn)) == FR_FAIL)
        goto ERROR;

    //start time
    if (frreport_body_l7_add_timeval(p_st_body_data, APM_REPORT_KEY_REQ_START_TIMESTAMP, &(p_st_l4_trans->st_request_time_first_byte)) == FR_FAIL)
        goto ERROR;

    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;
    ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    //send_time_us
    if (frreport_body_l7_add_long(p_st_body_data, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if (frreport_body_l7_add_long(p_st_body_data, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_body_data, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
    if (p_st_report_data == NULL)
        goto ERROR;

    //p_report_req p_report_comm添加到链表
    if (p_st_private->i_flag_oneway == 0)
    {
        i_ret = __tbinary_add_req_list(p_st_private, p_st_body_data);
        if (i_ret == FR_FAIL)
            goto ERROR;
    }

    __clear_timeout_node((&p_st_private->st_thrift_data_list), p_st_packet->st_timestamp);

    if (frreport_data_add_body(p_st_report_data, p_st_body_data) == FR_FAIL)
        goto ERROR;
    p_st_body_data = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    thrift_tbinary_session_reset(p_st_private);

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    if (p_st_body_data)
        frreport_body_free(&p_st_body_data);
    thrift_tbinary_session_reset(p_st_private);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * resp解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
int thrift_tbinary_resp_analyze(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = 0;
    unsigned long ul_tmp = 0;
    L7session_thrift_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data* p_st_report_data = NULL;
    Frlist_node *p_st_gotnode = NULL;
    Frreport_body_data *p_st_body_data = NULL;
    thrift_data *p_st_thrift_data = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_thrift_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if (p_st_body_data == NULL)
    {
        //创建数据链表
        p_st_body_data = frreport_body_new_l7(p_st_conn);
        if (p_st_body_data == NULL)
            goto ERROR;

        if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
        {
            p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_st_data == NULL)
        {
            p_st_private->p_st_data = bytebuff_creat();
            if (p_st_private->p_st_data == NULL)
                goto ERROR;
        }
    }

    //请求的字节数
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_st_data == NULL)
        goto ERROR;
    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    //分片包判断
    if (*(p_st_packet->p_payload+p_st_packet->ui_payload_len-1) != '\x00')
    {
        frreport_body_free(&p_st_body_data);
        return APM_L7_ANALYZE_TODO;
    }

    //resp解析
    i_ret = __resp_parse(p_st_private->p_st_data, p_st_private, p_st_body_data, p_st_conn);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    //取链表对应的request p_report_req p_report_comm
    p_st_gotnode = frlist_find(&(p_st_private->st_thrift_data_list), &(p_st_private->i_resp_id), __fields_list_node_find);
    if (p_st_gotnode == NULL)
        goto ERROR;

    p_st_thrift_data = (thrift_data *)p_st_gotnode->data;

    //数据上报
    FRREPORT_BODY_L7LIST_SET_REQ(p_st_body_data, &p_st_thrift_data->p_report_req);
    FRREPORT_BODY_L7LIST_SET_COMM(p_st_body_data, &p_st_thrift_data->p_report_comm);
    p_st_thrift_data->p_report_req = NULL;
    p_st_thrift_data->p_report_comm = NULL;

    //start time
    if (frreport_body_l7_add_timeval(p_st_body_data, APM_REPORT_KEY_RESP_START_TIMESTAMP, &(p_st_l4_trans->st_response_time_first_byte)) == FR_FAIL)
        goto ERROR;

    //server time
    ul_tmp = frtime_diff(&p_st_thrift_data->st_l4_trans.st_request_time, &(p_st_l4_trans->st_response_time_first_byte));
    if (frreport_body_l7_add_ulong(p_st_body_data, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    frlist_node_free(&p_st_private->st_thrift_data_list, p_st_gotnode, FR_YES, frthritf_list_node_free);

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    if (frreport_body_l7_add_long(p_st_body_data, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
        goto ERROR;

    //down load time
    ul_tmp = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &(p_st_l4_trans->st_response_time));
    if (frreport_body_l7_add_long(p_st_body_data, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_body_data, APM_REPORT_KEY_RESP_END_TIMESTAMP, &(p_st_l4_trans->st_response_time)) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
    if (p_st_report_data == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_body_data) == FR_FAIL)
        goto ERROR;
    p_st_body_data = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    thrift_tbinary_session_reset(p_st_private);

    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    if (p_st_body_data)
        frreport_body_free(&p_st_body_data);
    thrift_tbinary_session_reset(p_st_private);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 私有信息reset
 *
 * \param p_private_session  (私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
void thrift_tbinary_session_reset(void *p_private_session)
{
    L7session_thrift_private *p_st_private = NULL;

    if (p_private_session == NULL)
        return;

    p_st_private = (L7session_thrift_private*)p_private_session;

    if (p_st_private)
    {
        memset(&(p_st_private->st_l4_trans), 0x00, sizeof(L4_transaction));

        if (p_st_private->p_st_data)
        {
            bytebuff_free(&(p_st_private->p_st_data));
            p_st_private->p_st_data = NULL;
        }

        p_st_private->i_req_id = 0;
        p_st_private->i_resp_id = 0;
        p_st_private->i_flag_oneway = 0;
    }

    return;
}
